using System;
using System.Net.Sockets;
using XcoAppSpaces.Transport.Sockets.Auth.Contract;
using XcoAppSpaces.Transport.Sockets.Auth.Contract.DoClientHandshake;

namespace XcoAppSpaces.Transport.Sockets.Auth
{
	public class DoClientHandshake : IDoHandshake
	{
		private IPrepareAuthentication prepareAuthentication;
		private ISendGreeting sendGreeting;
		private IReceiveChallenge receiveChallenge;
		private ISendResponse sendResponse;
		private IFinishAuthentication finishAuthentication;

		internal DoClientHandshake(IPrepareAuthentication prepareAuthentication, ISendGreeting sendGreeting, IReceiveChallenge receiveChallenge, ISendResponse sendResponse, IFinishAuthentication finishAuthentication)
		{
			this.prepareAuthentication = prepareAuthentication;
			this.sendGreeting = sendGreeting;
			this.receiveChallenge = receiveChallenge;
			this.sendResponse = sendResponse;
			this.finishAuthentication = finishAuthentication;

			prepareAuthentication.Out_Connection += sendGreeting.In_Connection;
			sendGreeting.Out_ValidConnection += receiveChallenge.In_Connection;
			receiveChallenge.Out_ValidConnection += sendResponse.In_Connection;
			sendResponse.Out_ValidConnection += finishAuthentication.In_Connection;
			finishAuthentication.Out_TcpClient += _ => this.Out_AuthenticatedConnection(_);

			prepareAuthentication.Out_Error += _ => this.Out_InvalidConnection(_);
			sendGreeting.Out_InvalidConnection += _ => this.Out_InvalidConnection(_);
			receiveChallenge.Out_InvalidConnection += _ => this.Out_InvalidConnection(_);
			sendResponse.Out_InvalidConnection += _ => this.Out_InvalidConnection(_);
		}

		public void In_Connection(TcpClient tcpClient)
		{
			prepareAuthentication.In_TcpClient(tcpClient);
		}

        public event TcpClientHandler Out_AuthenticatedConnection;

        public event TcpClientHandler Out_InvalidConnection;

		public void Inject(SecuritySettings dependency)
		{
			prepareAuthentication.Inject(dependency);
			sendGreeting.Inject(dependency);
			receiveChallenge.Inject(dependency);
			sendResponse.Inject(dependency);
		}

		public static DoClientHandshake CreateDefaultInstance()
		{
			return new DoClientHandshake(new PrepareAuthentication(), new SendGreeting(), new ReceiveChallenge(), new SendResponse(), new FinishAuthentication());
		}
	}
}
